﻿/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 *
 * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 */
#include "homepagewidget.h"
#include "ui_homepagewidget.h"

#include <QLabel>
#include <QSignalMapper>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QListWidget>
#include <QDBusInterface>
#include <QDebug>
#include <QScrollBar>
#include <QStringList>

#include <QSvgRenderer>
#include "mainwindow.h"
#include "utils/functionselect.h"
#include "interface/ukcccommon.h"
using namespace ukcc;
#include "flowlayout.h"
#include "utils/modulefactory.h"

#define STYLE_FONT_SCHEMA  "org.ukui.style"
#define MODULE_LABEL_MAXWIDTH 198

const QStringList KexcludeModule{"update","security","application","search_f"};

HomePageWidget::HomePageWidget(QWidget *parent, QMap<QString, QGSettings *> map) :
    QWidget(parent),
    vecGsettins(map),
    ui(new Ui::HomePageWidget)
{
    qApp->installEventFilter(this);
    ui->setupUi(this);
    // 获取主窗口
    this->setParent(parent);
    pmainWindow = (MainWindow *)parentWidget();

    // 初始化首页
    initUI();
    ui->scrollArea->viewport()->setAttribute(Qt::WA_TranslucentBackground);
    ui->scrollArea->setStyleSheet("QScrollArea{background-color: transparent;}");
    ui->scrollArea->verticalScrollBar()->setProperty("drawScrollBarGroove", false);
    ui->scrollArea->verticalScrollBar()->setVisible(false);

}

HomePageWidget::~HomePageWidget()
{
    delete ui;
    ui = nullptr;
}

void HomePageWidget::initUI() {
    FlowLayout * flowLayout = new FlowLayout(ui->widget_2, true, 0);
    flowLayout->setContentsMargins(70, 0, 70, 0);
    mModuleMap = UkccCommon::getModuleHideStatus();

    QSignalMapper * moduleSignalMapper = new QSignalMapper(this);
    int totalModule = ModulesFactory::size();
    for(int index = 0; index < totalModule; index++) {
        ModuleInfo *curModuleInfo = ModulesFactory::getModuleInfoByIndex(index);
        if (curModuleInfo == nullptr) {
            continue;
        }
        //获取当前模块名
        const QString locale = QLocale::system().name();
        QString modulenamei18nString = curModuleInfo->getModuleNameLocale(locale);
        QString modulenameString = curModuleInfo->moduleName;

        if ((mModuleMap.keys().contains(modulenameString) && !mModuleMap[modulenameString].toBool())
                || (UkccCommon::isTablet() && KexcludeModule.contains(modulenameString))) {
            continue;
        }

        // pangw无安全模块-不显示 社区无更新和安全-不显示
        if ((modulenameString == "security" || modulenameString == "update") && UkccCommon::isCommunity()) {
            continue;
        }

        //三权分立下非root用户，不可设置网络、时间语言、更新
#ifdef WITHKYSEC
        if (!kysec_is_disabled() && kysec_get_3adm_status() && (getuid() || geteuid())){
            if (modulenameString == "network" || modulenameString == "datetime" || modulenameString == "update") {
                continue;
            }
        }
#endif

        //构建首页10个模块
        //基础Widget
        QWidget * baseWidget = new QWidget();
        baseWidget->setAttribute(Qt::WA_DeleteOnClose);
        baseWidget->setObjectName("itemBaseWidget");
        //baseWidget 的顶级布局
        QVBoxLayout * baseVerLayout = new QVBoxLayout(baseWidget);
        baseVerLayout->setMargin(0);
        baseVerLayout->setSpacing(0);
        //包含显示内容的布局
        QBoxLayout * majorHorLayout = new QHBoxLayout();
        majorHorLayout->setMargin(0);
        majorHorLayout->setSpacing(0);

        //内容Widget的构建
        QPushButton * widget = new QPushButton();
        QString picModuleName = modulenameString;
        widget->setMinimumWidth(300);
        widget->setMinimumHeight(97);
        widget->setAttribute(Qt::WA_DeleteOnClose);
        widget->setProperty("useButtonPalette", true);

        if (picModuleName == "search_f") {
            picModuleName = "search";
        }
        widget->setObjectName("itemWidget");
        widget->setFlat(true);
        QHBoxLayout * mainHorLayout = new QHBoxLayout(widget);
        mainHorLayout->setMargin(16);
        mainHorLayout->setSpacing(16);

        QLabel * logoLabel = new QLabel(widget);
        logoLabel->setFixedSize(48, 48);
        logoLabel->setObjectName("logoLabel");
        logoLabel->setScaledContents(true);
        QString themeIconName = curModuleInfo->themeIconName;
        QString localIconName = curModuleInfo->localIconName;
        logoLabel->setPixmap(QIcon::fromTheme(themeIconName,QIcon(localIconName))
                             .pixmap(logoLabel->size()));
        const QByteArray settingId(STYLE_FONT_SCHEMA);
        if (QGSettings::isSchemaInstalled(settingId)) {
            QGSettings *mQtSettings = new QGSettings(settingId, QByteArray(), this);
            connect(mQtSettings, &QGSettings::changed, this, [=](QString key) {
                if (key == "iconThemeName") {
                    logoLabel->setPixmap(QIcon::fromTheme(themeIconName,QIcon(localIconName))
                                         .pixmap(logoLabel->size()));
                }
            });
        }
        QVBoxLayout * rightVerLayout = new QVBoxLayout();
        rightVerLayout->setContentsMargins(0, 2, 0, 0);
        rightVerLayout->setSpacing(8);

        QLabel * titleLabel = new QLabel(widget);
        titleLabel->setObjectName("mptitleLabel");
        titleLabel->setText(modulenamei18nString);

        QHBoxLayout * funcHorLayout = new QHBoxLayout();
        funcHorLayout->setSpacing(8);

        uint AllWidth = 0;
        QList<TristateLabel *> Labels;
        QList<PluginInfo> tmpList = curModuleInfo->pluginInfoList;
        int showModuleCount = 0;
        for (int funcIndex = 0; funcIndex < tmpList.size(); funcIndex++){
            PluginInfo single = tmpList.at(funcIndex);

            //跳过不在首页显示的功能
            if (!single.mainShow)
                continue;
            if (mModuleMap.keys().contains(single.nameString.toLower())) {
                if (!mModuleMap[single.nameString.toLower()].toBool()) {
                    continue;
                }
            }
            QObject* pluginObj = ModulesFactory::getPluginObjectByName(single.namei18nString);
            if (pluginObj == nullptr) {
                continue;
            }

            QString textName = single.namei18nString;
            TristateLabel *label = new TristateLabel(textName, widget);

            if (single.isEnable) {
                Labels.append(label);
                AllWidth += label->width() + funcHorLayout->spacing();
            }
            // 显示后总label宽度大导致显示不全，隐藏后加载显示的label
            if (!single.isEnable || AllWidth > MODULE_LABEL_MAXWIDTH) {
                label->setVisible(false);
            }

            if (single.isEnable && showModuleCount == 0 && label->width() + funcHorLayout->spacing() > MODULE_LABEL_MAXWIDTH) {
                label->setVisible(true);
                if (setTextDynamic(label, textName)) {
                    label->setToolTip(textName);
                }
            }

            // 监听该插件是否启用
            if (vecGsettins.contains(single.oriNameString)) {
                // 插件未启用直接隐藏该label
               if (!vecGsettins[single.oriNameString]->get(SHOW_KEY).toBool())
                   label->setVisible(false);

                connect(vecGsettins[single.oriNameString], &QGSettings::changed,[=](QString key){
                    if (key == SHOW_KEY) {
                        CommonInterface* pluginInstance = qobject_cast<CommonInterface*>(pluginObj);
                        bool isShow = pluginInstance->isEnable() && vecGsettins[single.oriNameString]->get(SHOW_KEY).toBool();
                        // 动态调整在首页显示的插件池
                        if (isShow) {
                            if (!mLabels[index].contains(label)) {
                                mLabels[index].insert(funcIndex, label);
                            }
                            int MWidth = 0;
                            for (TristateLabel * label : mLabels[index]) {
                                if ((MWidth += label->width() + funcHorLayout->spacing()) < MODULE_LABEL_MAXWIDTH) {
                                    label->setVisible(true);
                                } else {
                                    label->setVisible(false);
                                }
                            }
                        } else {
                            if (mLabels[index].contains(label)) {
                                mLabels[index].removeOne(label);
                            }
                            label->setVisible(false);
                        }
                    }
                });
            }

            connect(label, SIGNAL(clicked()), moduleSignalMapper, SLOT(map()));
            moduleSignalMapper->setMapping(label, pluginObj);

            funcHorLayout->addWidget(label);
            ++showModuleCount;
        }
        mLabels.insert(index, Labels);
        funcHorLayout->addStretch();

        // 下属无插件，不显示
        if (curModuleInfo->pluginInfoList.size() == 0 || showModuleCount == 0) {
            widget->setVisible(false);
            continue;
        }

        const QByteArray styleID(STYLE_FONT_SCHEMA);
        QGSettings *stylesettings = new QGSettings(styleID, QByteArray(), this);
        connect(stylesettings,&QGSettings::changed, [=](QString key) {
            if ("systemFont" == key || "systemFontSize" == key) {
                 int MWidth = 0;
                 for (TristateLabel * label : Labels) {
                     QFontMetrics fontMetrics(this->font());
                     int fontSize = fontMetrics.width(label->text());
                     label->setFixedWidth(fontSize);
                     if ((MWidth += label->width() + funcHorLayout->spacing()) < MODULE_LABEL_MAXWIDTH) {
                         label->setVisible(true);
                     } else {
                         label->setVisible(false);
                     }
                 }
            }
        });
        connect(widget, &QPushButton::clicked, [=]() {
            //获取模块的第一项跳转
            QString firstFunc;
            QList<PluginInfo> tmpList = curModuleInfo->pluginInfoList;
            for (PluginInfo tmpStruct : tmpList) {
                bool isIntel = UkccCommon::isTablet();

                if ((isIntel && tmpStruct.namei18nString == "User Info")
                      || (!isIntel && tmpStruct.namei18nString == "User Info Intel")) {
                    continue;
                }

                if (!tmpStruct.isEnable) {
                    continue;
                }
                QObject* pluginObj = ModulesFactory::getPluginObjectByName(tmpStruct.namei18nString);
                if (pluginObj == nullptr) {
                    continue;
                }

                // 若该插件不启用，跳转为下一项
                if (vecGsettins.contains(tmpStruct.nameString)) {
                    QGSettings *msettings = vecGsettins[tmpStruct.nameString];
                    if (msettings) {
                        if (!msettings->get(SHOW_KEY).toBool()) {
                            continue;
                        }
                    }
                }
                if (mModuleMap.isEmpty() || !mModuleMap.contains(tmpStruct.nameString.toLower()) || mModuleMap[tmpStruct.nameString.toLower()].toBool()) {
                    firstFunc = tmpStruct.namei18nString;
                    UkccCommon::buriedSettings(tmpStruct.nameString, nullptr, "home clicked");
                    //跳转
                    pmainWindow->functionBtnClicked(pluginObj);
                    break;
                }
            }
        });

        rightVerLayout->addStretch();
        rightVerLayout->addWidget(titleLabel);
        rightVerLayout->addLayout(funcHorLayout);
        rightVerLayout->addStretch();

        mainHorLayout->addWidget(logoLabel);
        mainHorLayout->addLayout(rightVerLayout);
        mainHorLayout->addStretch();

        widget->setLayout(mainHorLayout);

        majorHorLayout->addWidget(widget);
        majorHorLayout->addStretch();

        baseVerLayout->addLayout(majorHorLayout);
        baseVerLayout->addStretch();

        baseWidget->setLayout(baseVerLayout);

        flowLayout->addWidget(baseWidget);
    }
    connect(moduleSignalMapper, SIGNAL(mapped(QObject*)), pmainWindow, SLOT(pluginBtnClicked(QObject*)));
}

bool HomePageWidget::setTextDynamic(QLabel *label, QString string)
{
    bool isOverLength = false;
    QFontMetrics fontMetrics(label->font());
    int labelValueSize = MODULE_LABEL_MAXWIDTH;
    int fontSize = fontMetrics.width(string);
    QString str = string;
    qDebug() << "fontSize:" << fontSize << ";labelValueSize:" << labelValueSize;
    if (fontSize >= labelValueSize) {
        str = fontMetrics.elidedText(string, Qt::ElideRight, labelValueSize);
        isOverLength = true;
    } else {

    }
    label->setText(str);
    return isOverLength;
}

QGSettings *HomePageWidget::setGsettingsPath(QList<char *> list ,  QString name)
{
    // 为每个插件创建动态QGSettings对象，用于监听插件是否隐藏
    QByteArray ba;
    char *path;
    ba = (QString("%1%2").arg(name).arg("/")).toUtf8();
    path = ba.data();
    const QByteArray id(PLUGINS_SCHEMA);
    if (!QGSettings::isSchemaInstalled(id)) {
        return nullptr;
    }
    QGSettings *settings = nullptr;
    QString plugin = QString("%1%2%3").arg(PLUGINS_PATH).arg(name).arg("/");
    settings = new QGSettings(id, plugin.toUtf8().data(), this);

    //判断是否已存在该路径,不存在则赋初值
    for (int j = 0; j < list.count(); j++) {
        if (!qstrcmp(path, list.at(j))){
            return settings;
        }
    }
    settings->set(PLUGIN_NAME , name);
    settings->set(SHOW_KEY , true);
    return settings;
}

const QPixmap HomePageWidget::loadSvg(const QString &fileName, COLOR color)
{
    int size = 48;
    const auto ratio = qApp->devicePixelRatio();
    if ( 2 == ratio) {
        size = 96;
    } else if (3 == ratio) {
        size = 144;
    }
    QPixmap pixmap(size, size);
    QSvgRenderer renderer(fileName);
    pixmap.fill(Qt::transparent);

    QPainter painter;
    painter.begin(&pixmap);
    renderer.render(&painter);
    painter.end();

    pixmap.setDevicePixelRatio(ratio);
    return drawSymbolicColoredPixmap(pixmap, color);
}

QPixmap HomePageWidget::drawSymbolicColoredPixmap(const QPixmap &source, COLOR cgColor)
{
    QImage img = source.toImage();
    for (int x = 0; x < img.width(); x++) {
        for (int y = 0; y < img.height(); y++) {
            auto color = img.pixelColor(x, y);
            if (color.alpha() > 0) {
                if ( WHITE == cgColor) {
                    color.setRed(255);
                    color.setGreen(255);
                    color.setBlue(255);
                    img.setPixelColor(x, y, color);
                } else if( BLACK == cgColor) {
                    color.setRed(0);
                    color.setGreen(0);
                    color.setBlue(0);
                    img.setPixelColor(x, y, color);
                } else if (GRAY == cgColor) {
                    color.setRed(152);
                    color.setGreen(163);
                    color.setBlue(164);
                    img.setPixelColor(x, y, color);
                } else if(HIGHLIGHT == cgColor){
                    QColor highLightColor = palette().color(QPalette::Highlight);
                    color.setRed(highLightColor.red());
                    color.setGreen(highLightColor.green());
                    color.setBlue(highLightColor.blue());
                    img.setPixelColor(x, y, color);
                }
                else {
                    return source;
                }
            }
        }
    }
    return QPixmap::fromImage(img);
}


bool HomePageWidget::eventFilter(QObject *watched, QEvent *event)
{
    if (event->type() == QEvent::MouseMove) {
        if (ui->scrollArea->geometry().contains(this->mapFromGlobal(QCursor::pos()))) {
            ui->scrollArea->verticalScrollBar()->setVisible(true);
        } else {
            ui->scrollArea->verticalScrollBar()->setVisible(false);
        }
    }
     return QObject::eventFilter(watched, event);
}

